package templateExecel2.fram;

import com.google.common.collect.Sets;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import templateExecel2.utils.FileUtils;

import javax.script.*;
import java.awt.*;
import java.io.InputStream;
import java.util.*;

public class Js {

    private static ScriptEngine engine;
    private static Bindings bindings;

    static {

        ScriptEngineManager manager = new ScriptEngineManager();
        engine = manager.getEngineByName("nashorn");
        bindings = engine.getBindings(ScriptContext.GLOBAL_SCOPE);

        //初始化脚本
        try {
            InputStream stream = Js.class.getClassLoader().getResource("init.js").openConnection().getInputStream();
            String read = FileUtils.read(stream);
            //执行初始化脚本
            engine.eval(read);
        } catch (Exception e) {
            throw new Error(e);
        }

        set("console", new Console());
        set("_java", new Java());
    }


    public static Object exe(String js) throws ScriptException {
        try {
            // System.out.println(js);
            return engine.eval(js);
        } catch (Exception e) {
            throw e;
        }

    }

    public static Object call(String method, Object... p) {
        try {
            return ((Invocable) engine).invokeFunction(method, p);
        } catch (ScriptException | NoSuchMethodException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static Object set(String k, Object v) {
        return bindings.put(k, v);
    }


    public static Object put(String k, Object v) {
        return bindings.put(k, v);
    }



    public static Object remove(String k) {
        return bindings.remove(k);
    }

    public static Object get(String k) {
        return bindings.get(k);
    }

    public static void putAll(Map<String, Object> all) {
        bindings.putAll(all);
    }

    public static class Console {
        public void log(String obj) {
            System.out.println(call("objToString", obj));
        }

        public void log() {
            System.out.println();
        }

    }

    public static class CacheTree {

        private static class Node {
            private Map<Object, Node> subMap;
            private Object value;
        }

        //TODO  第一级参数
        private Map<Object, Node> subMap;

        private Object value;

        void set(Object[] args, Object data) {
            if (args.length == 0) {
                value = data;
                return;
            }

            if (subMap == null) {
                subMap = new HashMap<>();
            }

            //从第一级参数开始递归
            Map<Object, Node> sm = subMap;

            Node node = null;

            //一直找到最后一级参数
            for (Object key : args) {
                node = sm.computeIfAbsent(key, k -> new Node());
                if (node.subMap == null) {
                    node.subMap = new HashMap<>();
                }
                sm = node.subMap;
            }

            node.value = data;

        }

        Object get(Object[] args) {
            if (args.length == 0) {
                return value;
            }
            if (subMap == null) {
                return null;
            }
            Map<Object, Node> sm = subMap;

            Node node = null;

            //一直找到最后一级参数
            for (Object key : args) {
                node = sm.get(key);
                if (node == null || node.subMap == null) {
                    return null;
                }
                sm = node.subMap;
            }

            return node.value;
        }

    }

    public static class Java {

        //缓存数
        private Map<String, CacheTree> treeMap = new HashMap<>();

        public void cachePut(String name, Object[] args, Object data) {
            CacheTree cacheTree = treeMap.computeIfAbsent(name, k -> new CacheTree());
            cacheTree.set(args, data);
        }

        public Object cacheGet(String name, Object[] args) {

            CacheTree cacheTree = treeMap.get(name);
            if (cacheTree == null) {
                return null;
            }

            return cacheTree.get(args);
        }

        //清空现有缓存
        public void clearCache() {

            System.out.println("调用内存清理");

            treeMap = new HashMap<>();

            //辅助gc
            System.gc();

        }


    }


    public static void main(String[] args) throws ScriptException {

        Object[] as = new Object[]{1, 2};

        Js.set("as", as);

        Js.exe("console.log(reversal(as))");

        Js.exe("console.log(reversal(as)===reversal(as))");

    }


}
